﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Linq;
using System.Linq;
using System.Windows.Input;

using GalaSoft.MvvmLight.Command;

using Organizer.Model;

namespace Organizer.ViewModel
{
    using System;
    using System.Collections;

    using Microsoft.Phone.Tasks;
    using Microsoft.Phone.UserData;

    /// <summary>
    /// The Contact view model.
    /// </summary>
    public class MansViewModel : BaseViewModel
    {
        #region Fields

        SaveContactTask MyConatct_Task = new SaveContactTask();
        AddressChooserTask MyAddress_Task = new AddressChooserTask();

        /// <summary>
        /// The _edited Contact (Cloned object of currently edited Contact).
        /// </summary>
        private Man _editedMan;

        /// <summary>
        /// The _Contact to edit.
        /// </summary>
        private Man _manToEdit;

        /// <summary>
        /// The status.
        /// </summary>
        private State status = State.Normal;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ContactViewModel"/> class.
        /// </summary>
        public MansViewModel()
        {
            NotifyPropertyChanged("Mans");
            this.AddCommand = new RelayCommand(() => AddContact());
            this.EditCommand = new RelayCommand<Man>(org => { EditMan(org); });
            this.SaveCommand = new RelayCommand(() => SaveMan());
            this.CancelCommand = new RelayCommand(() => CancelContact());
            this.CancelSelectionCommand = new RelayCommand(() => CancelSelection());
            this.ManageCommand = new RelayCommand(() => ManageSelection());
            this.DeleteCommand = new RelayCommand(() => DeleteContacts());
            this.RefreshCommand = new RelayCommand(() => RefreshMan());
            this.BackKeyPressCommand = new RelayCommand<CancelEventArgs>(e => BackKeyPressAction(e));
            Status = State.Normal;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets AddCommand.
        /// </summary>
        public ICommand AddCommand { get; set; }

        /// <summary>
        /// Gets or sets BackKeyPressCommand.
        /// </summary>
        public ICommand BackKeyPressCommand { get; set; }

        /// <summary>
        /// Gets or sets CancelCommand.
        /// </summary>
        public ICommand CancelCommand { get; set; }

        /// <summary>
        /// Gets or sets CancelSelectionCommand.
        /// </summary>
        public ICommand CancelSelectionCommand { get; set; }

        /// <summary>
        /// Gets or sets DeleteContactsCommand.
        /// </summary>
        public ICommand DeleteCommand { get; set; }

        /// <summary>
        /// Gets or sets EditCommand.
        /// </summary>
        public ICommand EditCommand { get; set; }

        /// <summary>
        /// Gets or sets EditedMan.
        /// </summary>
        public Man EditedMan
        {
            get
            {
                if (this._editedMan == null)
                {
                    this._editedMan = new Man();
                }

                return this._editedMan;
            }

            set
            {
                this._editedMan = value;
                NotifyPropertyChanged(() => this.EditedMan);
            }
        }

        /// <summary>
        /// Gets or sets ManageCommand.
        /// </summary>
        public ICommand ManageCommand { get; set; }

        /// <summary>
        /// Gets or sets ContactToEdit.
        /// </summary>
        public Man ManToEdit
        {
            get
            {
                return this._manToEdit ?? (this._manToEdit = new Man());
            }

            set
            {
                _manToEdit = value;
                NotifyPropertyChanged(() => this.ManToEdit);
            }
        }

        /// <summary>
        /// Gets Contacts from context.
        /// </summary>
        public List<Man> Mans
        {
            get
            {
                var mans = OrganizerDataContext.Instance.Mans.Where(man => man.Id != Guid.Empty).ToList();
                mans.Sort(new Man.SortByName());
                return mans;
            }
        }

        /// <summary>
        /// Gets Contacts from context.
        /// </summary>
        public List<Organization> OrganizationsList
        {
            get
            {
                var organizations = OrganizerDataContext.Instance.Organizations.ToList();
                organizations.Sort(new Organization.SortByName());
                return organizations;
            }
        }

        /// <summary>
        /// Gets or sets RefreshCommand.
        /// </summary>
        public ICommand RefreshCommand { get; set; }

        /// <summary>
        /// Gets or sets SaveCommand.
        /// </summary>
        public ICommand SaveCommand { get; set; }

        /// <summary>
        /// Gets or sets Status. Property to control icons in AppBar.
        /// </summary>
        public State Status
        {
            get
            {
                return status;
            }

            set
            {
                status = value;
                NotifyPropertyChanged(() => this.Status);
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// Manage selection.
        /// </summary>
        public void ManageSelection()
        {
            Status = State.ManageSelection;
            NotifyPropertyChanged(() => this.Mans);
        }

        #endregion

        #region Methods

        /// <summary>
        /// Add Contact.
        /// </summary>
        private void AddContact()
        {
            Status = State.Edit;
            this.EditedMan = new Man();
            ManToEdit = new Man();
            NotifyPropertyChanged(() => this.Mans);
        }

        /// <summary>
        /// The back key press action.
        /// </summary>
        /// <param name="e">
        /// The CancelEventArgs.
        /// </param>
        private void BackKeyPressAction(CancelEventArgs e)
        {
            if (Status == State.Edit)
            {
                e.Cancel = true;
                Status = State.Normal;
                //this.EditedMan = null;
                NotifyPropertyChanged(() => this.Mans);
            }

            if (Status == State.ManageSelection)
            {
                Mans.ForEach(x =>
                {
                    if (x.IsSelectedMultiSelect)
                    {
                        x.IsSelectedMultiSelect = false;
                    }
                    NotifyPropertyChanged(string.Empty);
                });
                e.Cancel = true;
                Status = State.Normal;
                //this.EditedMan = null;
                NotifyPropertyChanged(() => this.Mans);
            }
        }

        /// <summary>
        /// Cancel Contact.
        /// </summary>
        private void CancelContact()
        {
            Status = State.Normal;
            //this.EditedMan = null;
            OrganizerDataContext.Instance.SubmitChanges();
            NotifyPropertyChanged(() => this.Mans);
        }

        /// <summary>
        /// Cancel selection.
        /// </summary>
        private void CancelSelection()
        {
            Mans.ForEach(x =>
                {
                    if (x.IsSelectedMultiSelect)
                    {
                        x.IsSelectedMultiSelect = false;
                    }

                    NotifyPropertyChanged(string.Empty);
                });
            NotifyPropertyChanged(() => this.Mans);
            Status = State.Normal;
        }

        /// <summary>
        /// Delete Contacts.
        /// </summary>
        private void DeleteContacts()
        {
            var orgs = new List<Man>();
            Mans.ForEach(x =>
                {
                    if (x.IsSelectedMultiSelect)
                    {
                        orgs.Add(x);
                    }
                });
            try
            {
                OrganizerDataContext.Instance.Mans.DeleteAllOnSubmit(orgs);
                OrganizerDataContext.Instance.SubmitChanges();
            }
            catch
            {
                foreach (ObjectChangeConflict o in OrganizerDataContext.Instance.ChangeConflicts)
                {
                    o.Resolve(RefreshMode.KeepChanges);
                }

                OrganizerDataContext.Instance.SubmitChanges();
            }

            Status = State.Normal;
            NotifyPropertyChanged(() => this.Mans);
        }

        /// <summary>
        /// Edit Contact.
        /// </summary>
        /// <param name="man">
        /// The Contact to edit.
        /// </param>
        private void EditMan(Man man)
        {
            ManToEdit = man;
            this.EditedMan = Man.Create(man);
            Status = State.Edit;
            NotifyPropertyChanged(() => this.Mans);
        }

        /// <summary>
        /// Refresh Contact.
        /// </summary>
        private void RefreshMan()
        {
            NotifyPropertyChanged(() => this.Mans);
        }

        /// <summary>
        /// Save Contact.
        /// </summary>
        private void SaveMan()
        {
            ManToEdit.Name = this.EditedMan.Name;
            ManToEdit.Organization = this.EditedMan.Organization;

            if (!string.IsNullOrEmpty(ManToEdit.Name))
            {
                if (!Mans.Contains(ManToEdit))
                {
                    OrganizerDataContext.Instance.Mans.InsertOnSubmit(ManToEdit);
                }               
                OrganizerDataContext.Instance.SubmitChanges();
                Status = State.Normal;
                NotifyPropertyChanged(() => this.Mans);
            }
        }

        #endregion
    }
}
